V2EX

您所在的位置:网站首页 v2ex 论坛 V2EX

V2EX

2023-04-12 01:32| 来源: 网络整理| 查看: 265

hxndg:

trycrackme 的下载地址为 https://crackmes.one/crackme/61c8deff33c5d413767ca0ea ,直接从汇编就能看出来到底在做什么

Dump of assembler code for function main: # 标准开局,保存堆栈 0x00005555555551af : push %rbp 0x00005555555551b0 : mov %rsp,%rbp 0x00005555555551b3 : sub $0xe0,%rsp #存储 argc & argv ,不过这里没用到 0x00005555555551ba : mov %edi,-0xd4(%rbp) 0x00005555555551c0 : mov %rsi,-0xe0(%rbp) 0x00005555555551c7 : mov %fs:0x28,%rax 0x00005555555551d0 : mov %rax,-0x8(%rbp) 0x00005555555551d4 : xor %eax,%eax # 注意这个常量,是我们比较的关键 0x00005555555551d6 : movabs $0x3534323773734034,%rax # 存储到了-0xbb(%rbp)的位置 0x00005555555551e0 : mov %rax,-0xbb(%rbp) # 给上面的常量补充了两个字节的数字,拼接到最后面,拼接完以后看一下具体的内容 # (gdb) x/16xb 140737488347509 # 0x7fffffffe175: 0x34 0x40 0x73 0x73 0x37 0x32 0x34 0x35 # 0x7fffffffe17d: 0x33 0x36 0x00 0x00 0x00 0x00 0x00 0x00 0x00005555555551e7 : movw $0x3633,-0xb3(%rbp) 0x00005555555551f0 : movb $0x0,-0xb1(%rbp) 0x00005555555551f7 : lea -0xbb(%rbp),%rax 0x00005555555551fe : mov %rax,%rdi 0x0000555555555201 : callq 0x555555555050 # 存储我们刚才拼接出来的字符串长度,明确地看出来是 10 0x0000555555555206 : mov %eax,-0xc0(%rbp) 0x000055555555520c : mov $0x0,%eax # 调用 banner 打印一些 flag ,没有啥用,不用管 0x0000555555555211 : callq 0x555555555199 # 准备调用 printf 提示用户输入数据,格式化字符串为 Put the key: 0x0000555555555216 : lea 0xef9(%rip),%rax # 0x555555556116 0x000055555555521d : mov %rax,%rdi 0x0000555555555220 : mov $0x0,%eax 0x0000555555555225 : callq 0x555555555070 # 记住这个-0xb0(%rbp)的地址,这个是存储 scanf 输入进来的地址 0x000055555555522a : lea -0xb0(%rbp),%rax 0x0000555555555231 : mov %rax,%rsi 0x0000555555555234 : lea 0xee9(%rip),%rax # 0x555555556124 0x000055555555523b : mov %rax,%rdi 0x000055555555523e : mov $0x0,%eax 0x0000555555555243 : callq 0x555555555080 # 初始化两个变量,分别存储上面-0xbb(%rbp)字符串处理过的字符个数 # 和要算出来作为正确的 code 所处理过的字符个数 0x0000555555555248 : movl $0x0,-0xc8(%rbp) 0x0000555555555252 : movl $0x0,-0xc4(%rbp) |--- 0x000055555555525c : jmp 0x5555555552ab | # -0xc8(%rbp)是刚才那个常量字符串处理过的 byte 数,所以 cltq 下面那句就很明显了 |-----> 0x000055555555525e : mov -0xc8(%rbp),%eax | | 0x0000555555555264 : cltq | | # 这里的意思是把刚才-0xbb(%rbp)字符串的字符,hex 形式丢到 eax | | 0x0000555555555266 : movzbl -0xbb(%rbp,%rax,1),%eax | | # 先做有符号数拓展,再做无符号数拓展,不过都小于 0x80 ,所以无所谓了 | | 0x000055555555526e : movsbl %al,%eax | | 0x0000555555555271 : movzbl %al,%eax | | 0x0000555555555274 : mov -0xc4(%rbp),%edx | | 0x000055555555527a : movslq %edx,%rdx | | # rcx 存储了计算结果的首地址, -0x70(%rbp)是我们最后比较的参照物的地址 | | 0x000055555555527d : lea -0x70(%rbp),%rcx | | # 加上已经结算过的结果,实际上就是挪动指针,存储下面 sprintf 的结果 | | 0x0000555555555281 : add %rdx,%rcx | | 0x0000555555555284 : mov %eax,%edx | | # 这个字符是 %02x | | 0x0000555555555286 : lea 0xe9a(%rip),%rax # 0x555555556127 | | 0x000055555555528d : mov %rax,%rsi | | 0x0000555555555290 : mov %rcx,%rdi | | 0x0000555555555293 : mov $0x0,%eax | | # 这里调用 sprintf 的含义就非常清楚了,从 hex 编码转换为字符串 | | # 原先是 hex 0x34 ,那么转换为字符串\"34\" | | 0x0000555555555298 : callq 0x555555555090 | | # hex 字符串处理过一 byte 后挪一 | | # 而 sprintf 处理的结果是 2byte (两个 char 字符) | | 0x000055555555529d : addl $0x1,-0xc8(%rbp) | | 0x00005555555552a4 : addl $0x2,-0xc4(%rbp) | | #开始处理,先找到第一个字符,看看和上面的字符串长度 10 的大小,判断有没有处理完 | ---> 0x00005555555552ab : mov -0xc8(%rbp),%eax | 0x00005555555552b1 : cmp -0xc0(%rbp),%eax |------ 0x00005555555552b7 : jl 0x55555555525e 0x00005555555552b9 : lea -0x70(%rbp),%rax 0x00005555555552bd : mov %rax,%rdi 0x00005555555552c0 : callq 0x555555555050 0x00005555555552c5 : mov %rax,%rdx # 算出来的正确的 code 0x00005555555552c8 : lea -0x70(%rbp),%rcx # 输入的 code 0x00005555555552cc : lea -0xb0(%rbp),%rax 0x00005555555552d3 : mov %rcx,%rsi 0x00005555555552d6 : mov %rax,%rdi # 比较 0x00005555555552d9 : callq 0x555555555030 0x00005555555552de : test %eax,%eax |----0x00005555555552e0 : je 0x5555555552fd | 0x00005555555552e2 : lea 0xe43(%rip),%rax # 0x55555555612c | 0x00005555555552e9 : mov %rax,%rdi | 0x00005555555552ec : mov $0x0,%eax | 0x00005555555552f1 : callq 0x555555555070 | 0x00005555555552f6 : mov $0xffffffff,%eax | 0x00005555555552fb : jmp 0x555555555316 | # 这里就是正确的结果,所以我们只需要输入一个字符串和上面常量字符串从 hex 到字符串转换的结果即可 |--->0x00005555555552fd : lea 0xe3b(%rip),%rax # 0x55555555613f 0x0000555555555304 : mov %rax,%rdi 0x0000555555555307 : mov $0x0,%eax 0x000055555555530c : callq 0x555555555070 0x0000555555555311 : mov $0x0,%eax 0x0000555555555316 : mov -0x8(%rbp),%rdx 0x000055555555531a : sub %fs:0x28,%rdx 0x0000555555555323 : je 0x55555555532a 0x0000555555555325 : callq 0x555555555060 0x000055555555532a : leaveq 0x000055555555532b : retq End of assembler dump.

简单说一下过程

先从常量拼接出来要产生的字符串,0x3534323773734034 拼接 0x3633 对每一 byte 调用 sprintf ,使用格式:%02x ,从 hex 转换为两 byte 的字符串 转换完的结果和我们输入的结果做对比,一致则成功


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3